using System;
using Microsoft.SPOT;

namespace Gadgeteer.Modules.Community.XBee
{
    /// <summary>
    /// The response of issuing an AT command
    /// </summary>
    public class ATResponse : BaseAPIMessage
    {
        /// <summary>
        /// The 2 char command
        /// </summary>
        public string ATCommand { get; private set; }
        /// <summary>
        /// The status (e.g. OK, Error)
        /// </summary>
        public ushort CommandStatus { get; private set; }
        /// <summary>
        /// the numerical value if appropriate
        /// </summary>
        public int ReturnedValue { get; set; }
        /// <summary>
        /// Bytes returned
        /// </summary>
        public byte[] ReturnedBytes { get; set; }

        /// <summary>
        /// The message type is always ATResponse
        /// </summary>
        protected override ushort MessageType
        {
            get { return (ushort)APIMessageEnum.ATResponse; }
        }

        /// <summary>
        /// returns 'ATResponse'
        /// </summary>
        /// <returns>'ATResponse'</returns>
        protected override string MessageTypeToString()
        {
            return APIMessageEnum.ATResponse.ToString();
        }

        /// <summary>
        /// parses the message bytes, gets the ATCommand, CommandStatus, and any command data
        /// </summary>
        /// <param name="message">message</param>
        public override void ParseMessageBody(byte[] message)
        {
            ATCommand = new string(new char[] { Convert.ToChar(message[5]), Convert.ToChar(message[6]) });
            CommandStatus = (ushort)message[7];

            ParseCommandData(message);
            
        }

        /// <summary>
        /// The body of the message
        /// </summary>
        /// <returns>ATCommand, CommandStatus, and any command data</returns>
        public override string MessageBodyToString()
        {
            return "AT Command: " + ATCommand + "\n"
                 + "CommandStatus: " + CommandStatusToString() + "\n"
                 + CommandDataToString();
        }

        private string CommandStatusToString()
        {
            switch (CommandStatus)
            {
                case 0x00:
                    return "OK";
                case 0x01:
                    return "ERROR";
                case 0x02: 
                    return "Invalid Command";
                case 0x03:
                    return "Invalid Parameter";
                case 0x04:
                    return "Tx Failure";
                default:
                    throw new XBeeClientException("CommandStatus " + CommandStatus.ToString() + " not understood");
            }
        }

        /// <summary>
        /// Parses the data section of the message
        /// </summary>
        /// <param name="message">message</param>
        protected virtual void ParseCommandData(byte[] message)
        {
            if(CommandStatus == 0x00)
            {
                switch (ATCommand)
                {
                    case "NP":
                        ReturnedValue = (int)message[8];
                        break;
                    case "SH":
                    case "SL":
                        ReturnedBytes = new byte[4];
                        Array.Copy(message, 8, ReturnedBytes, 0, 4);
                        break;
                    case "MY":
                        ReturnedBytes = new byte[2];
                        Array.Copy(message, 8, ReturnedBytes, 0, 2);
                        break;

                }
            }
        }

        /// <summary>
        /// The command data
        /// </summary>
        /// <returns>string of command data, bytes in Hex format</returns>
        protected virtual string CommandDataToString()
        {
            string result = String.Empty;

            // TODO: inneficient code, someone shoot me or get string builder support (NetMF 4.2 :))
            switch (ATCommand)
            {
                case "SH":
                case "SL":
                    for (int i = 0; i < 4; i++)
                    {
                        result += HexUtil.ToHexString(ReturnedBytes[i]);
                        if (i < 3)
                        {
                            result += ", ";
                        }
                    }
                    break;
                case "MY":
                    for (int i = 0; i < 2; i++)
                    {
                        result += HexUtil.ToHexString(ReturnedBytes[i]);
                        if (i < 1)
                        {
                            result += ", ";
                        }
                    }
                    break;
            }

            return result;
        }
    }
}
